package com.js.study.datastructs.linked1;

import javax.management.relation.RelationNotFoundException;

/**
 * @Author JiangSen
 * @DATE 2023/12/24 14:49
 */
public class MyLinkedList<E> {
    //private Node<E> head;// head node
    private Node<E> virtualHead;
    private int size;

    public MyLinkedList(){
        this.virtualHead = new Node<>(null,null);
        this.size = 0;
    }
    public boolean isEmpty(){
        return size ==0;
    }
    public int getSize(){
        return  size;
    }
    // add
    public void addFirst(E e){
       add(0,e);
    }
    public void addLast(E e){
        add(size,e);
    }
    public void add(int index, E e){
        if(index < 0 || index > size){
            throw new RuntimeException("error");
        }
        Node<E> prev = virtualHead;
        //从head开始遍历,找到插入点的前一个位置
        for(int i = 0;i<index;i++){
            prev = prev.next;
        }
        //第二个prev  存放原来的下一个节点. 通过构造函数放到新节点的尾部.
        prev.next = new Node<>(e,prev.next);
        size++;
    }
    // delete
    public E removeFirst(){
        return remove(0);
    }
    public E removeLast(){
        return remove(size -1);
    }
    public E remove(int index){
        if(index < 0 || index >= size){
            throw new RuntimeException("error0");
        }
        Node<E> prev = virtualHead;
        for(int i =0; i< index; i++){
            prev = prev.next;
        }
        //通过循环找到了前一个节点
        Node<E> deleteNode = prev.next;
        prev.next = prev.next.next;
        deleteNode.next = null;//置空,调用gc垃圾回收机制.
        size--;
        return deleteNode.e;
    }

    //update
    public E set(int index,E e){
        if(index < 0 || index >= size){
            throw new RuntimeException("error0");
        }
        Node<E> currentNode = virtualHead.next;
        //虚拟节点指向的真正的   头节点.
        for(int i = 0;i<index; i++){
            currentNode = currentNode.next;
        }
        currentNode.e = e;
        return currentNode.e;
    }
    // get
    public E getFirst(){
        return get(0);
    }
    public E getLast(){
        return get(size -1);
    }
    public E get(int index){
        if (index < 0 || index >= size) throw new RuntimeException("索引不在有效边界");
        Node<E> currentNode = virtualHead.next;
        for(int i =0; i<index; i++){
            currentNode = currentNode.next;
        }
        return currentNode.e;
    }
    //contains
    public boolean contain(E e){
        Node<E> next = virtualHead.next;
        while(next !=null){
            if(next.e.equals(e)){
                return true;
            }
            next = next.next;
        }
        return false;
    }
    //印
    public void print() {
        StringBuffer stringBuffer = new StringBuffer();
        Node<E> curentNode = virtualHead.next;
        while (curentNode != null) {
            stringBuffer.append(curentNode.e + "->");
            curentNode = curentNode.next;
        }
        stringBuffer.append("NULL");
        System.out.println("stringBuffer = " + stringBuffer.toString());
    }

    public void print2() {
        StringBuffer stringBuffer = new StringBuffer();

        //for (int i = 0; i < ; i++)
        for (Node<E> currentNode = virtualHead.next; currentNode != null; currentNode = currentNode.next) {
            stringBuffer.append(currentNode.e + "->");
        }
        stringBuffer.append("NULL");

        System.out.println(stringBuffer);
    }
    //测试
    public static void main(String[] args) {
        MyLinkedList<Integer> test = new MyLinkedList<>();

        for (int i = 0; i < 5; i++) {
            test.add(i, i + 1);
            test.print();
        }
        System.out.println();

        test.addFirst(111);
        test.print();


        test.addLast(999);
        test.print();

        test.add(4, 44);
        test.print();

        System.out.println("test.getFirst(): " + test.getFirst());
        System.out.println("test.getLast(): " + test.getLast());
        System.out.println("test.get(3): " + test.get(3));
        System.out.println("delete"+test.remove(0));
        System.out.println("test.contain(44): " + test.contain(44));
        test.print();
    }

}
